<?php
version_compare(PHP_VERSION, '5.2', '<') && exit('ewebby framework requires PHP 5.2 or newer.');

abstract class EWebby_WebApplication {
	public static $current;

	private $_services = array();
	public $modules;
	public $filters;
	public $autoLoadModules = false;
	public $defaultHandler;
	public $handler;
	public $handlerFile;
	public $handlersDirectory;
	public $handlersViewExtension;
	public $configuration;
	public $profile;
	public $cookieBag;
	public $supportCompression = true;
	public $cache;

	protected abstract function onRun();
	public function run() {
		self::$current = $this;
		
		set_magic_quotes_runtime(false);	// kill magic quotes
		require_once (FRAMEWORK_PATH . 'Runtime' . DIRECTORY_SEPARATOR . 'Importer.php');
		
				
		EWebby_Runtime_Importer::register();
		try {
			if ( $this->supportCompression
				&& isset ( $_SERVER ['HTTP_ACCEPT_ENCODING'] ) 
				&& substr_count( $_SERVER ['HTTP_ACCEPT_ENCODING'], 'gzip' )) {			
				ob_implicit_flush(0);
				ob_start('ob_gzhandler');
			}
			
			require_once (APP_PATH . 'config.php');

			$this->configuration = $__APPCONFIG__;
			$this->profile = EWebby_HttpProfile::getInstance();
			$this->cookieBag = EWebby_HttpCookieBag::getInstance();
			$this->cache = new EWebby_CacheTable();

			$this->onRun();
						
			// get the http-handler instance, then process the request
			$this->handler = EWebby_HttpHandlerFactory::create($this);
			if( $this->filters != null 
				&& is_array($this->filters) ) {
				foreach ($this->filters as $filter) {
					if( $filter instanceof EWebby_IHttpFilter ) {
						$filter->init($this);
					}
				}
			}
			
			if( $this->handler != null 
				&& ($this->handler instanceof EWebby_IHttpHandler)) {
				// load the web modules
				if( $this->autoLoadModules ) {
					$this->modules = EWebby_ModuleLoader::getModulesFrom($this);
				}
				
				// process the web modules (initialization)
				if( is_array($this->modules) ) {
					foreach ($this->modules as $module) {
						if( $module instanceof EWebby_WebModule 
							&& $module->getEnabled() ) {
							$module->init();
						}
					}
		
					foreach ($this->modules as $module) {
						if( $module instanceof EWebby_WebModule 
							&& $module->getEnabled() ) {
							$module->load();
						}
					}					
				}
				
				$this->handler->process($this);

				// process the web modules (shutdown)
				if( is_array($this->modules) ) {
					foreach ($this->modules as $module) {
						if( $module instanceof EWebby_WebModule  
							&& $module->getEnabled() ) {
							$module->shutdown();
						}
					}
				}
			} else {
				throw new EWebby_PageNotFoundException();
			}
		} catch (Exception $ex) {
			$this->onError($ex);
		}
		
		$this->end();
	}
	
	protected abstract function onEnd();
	public function end() {		
		if( $this->filters != null 
			&& is_array($this->filters) ) {
			foreach ($this->filters as $filter) {
				if( $filter instanceof EWebby_IHttpFilter ) {
					$filter->shutdown($this);
				}
			}											
		}
		$this->onEnd();
		EWebby_Runtime_Importer::unRegister();
		
		unset($this);
		exit(0);
	}
	
	protected abstract function onError($error);

	
	public function getServices() {
		return $this->_services;
	}
	public function containsService($serviceName) {
		return isset($this->_services[$serviceName]);
	}
	public function getService($serviceName) {
		if( !isset($this->_services[$serviceName]) ) {
			throw new EWebby_Exception('service does not exists');			
		}
		
		return $this->_services[$serviceName];
	}
	public function addService($serviceName, $service) {
		if( isset($this->_services[$serviceName]) ) {
			throw new EWebby_Exception('service already exists');			
		}
		
		$this->_services[$serviceName] = $service;
	}
	public function removeService($serviceName) {
		if( !isset($this->_services[$serviceName]) ) {
			throw new EWebby_Exception('service does not exists');			
		}
		
		unset($this->_services[$serviceName]);
	}	
}